package com.qding.park.manager.service.core.facade.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.qding.park.adapter.bsg.adapter.impl.BSGBaseDataAdapterImpl;
import com.qding.park.common.core.exceptions.BaseException;
import com.qding.park.common.core.exceptions.ExceptionMessage;
import com.qding.park.common.core.exceptions.IExceptionHandle;
import com.qding.park.common.core.exceptions.business.manager.service.ServiceCoreException;
import com.qding.park.common.utils.ListUtil;
import com.qding.park.manager.cache.ParkCacheInter;
import com.qding.park.manager.facade.core.service.ConfDateFacade;
import com.qding.park.manager.pojo.TbCar;
import com.qding.park.manager.pojo.TbParkingrule;
import com.qding.park.manager.pojo.TbParkspace;
import com.qding.park.manager.pojo.TbUserInfo;
import com.qding.park.manager.pojo.ap.ApParkTypeInfo;
import com.qding.park.manager.pojo.ap.ApUserCarInfo;
import com.qding.park.manager.pojo.enums.CardStatuEnum;
import com.qding.park.manager.pojo.enums.RecordStatusEnum;
import com.qding.park.manager.pojo.enums.UserTypeEnum;
import com.qding.park.manager.service.core.atomic.distributed.UserDBAtomic;
import com.qding.park.manager.service.core.mapper.TbCarMapper;
import com.qding.park.manager.service.core.mapper.TbParkingruleMapper;
import com.qding.park.manager.service.core.mapper.TbParkspaceMapper;
import com.qding.park.manager.service.core.mapper.TbUserInfoMapper;

/**
 * @author Administrator 配置数据
 */
@Service("confDateFacade_12")
public class BSGConfDateFacadeImpl implements ConfDateFacade {

    private static final Log _log = LogFactory.getLog(BSGConfDateFacadeImpl.class);

    @Autowired
    private IExceptionHandle exceptionHandle;

    @Autowired
    private TbParkspaceMapper tbParkspaceMapper;

    @Autowired
    private TbParkingruleMapper tbParkingruleMapper;

    @Autowired
    private TbCarMapper tbCarMapper;

    @Autowired
    private ParkCacheInter parkCacheInter;

    @Autowired
    private BSGBaseDataAdapterImpl bSGBaseDataAdapter;

    @Autowired
    private UserDBAtomic userDBAtomic;

    @Autowired
    private TbUserInfoMapper tbUserInfoMapper;

    @Override
    public void confSync() throws BaseException {
        _log.info("批量同步系统的车场配置数据!!!!");
        String simpleText = "";
        String detailText = "";
        // 查询所有的车场列表
        List<TbParkspace> parkSpaceList = tbParkspaceMapper.listAll();

        if (ListUtil.isEmpty(parkSpaceList)) {
            _log.info("车场列表为空，同步任务已完成");
            throw new ServiceCoreException(ServiceCoreException.TypeEnum.EXCEPTION_NO_DATA_FIND.getId(), null,
                    ExceptionMessage.createExceptionMessage(
                            ServiceCoreException.TypeEnum.EXCEPTION_NO_DATA_FIND.getDesc(), "车场列表为空", "车场列表为空"));
        }
        _log.info("同步车场的用户数据 size=" + parkSpaceList.size());
        for (TbParkspace park : parkSpaceList) {
            int parkId = park.getId();

            try {
                confSync(park.getId());
            } catch (BaseException e) {
                _log.error(e.getExceptionMessage(), e);
                exceptionHandle.handle(e);
                simpleText += e.getExceptionMessage().getSimpleText() + ";";
                detailText += e.getExceptionMessage().getDetailText() + ";";
            } catch (Exception e) {
                exceptionHandle.handle(e);
                simpleText += "未知" + ";";
                detailText += "未知" + ";";
            }
        }

        if (!StringUtils.isBlank(simpleText)) {
            throw new ServiceCoreException(ServiceCoreException.TypeEnum.EXCEPTION_NO_DATA_FIND.getId(), null,
                    ExceptionMessage.createExceptionMessage(
                            ServiceCoreException.TypeEnum.EXCEPTION_NO_DATA_FIND.getDesc(), simpleText, detailText));
        }

    }

    @Override
    public void confSync(int parkId) throws BaseException {

        String simpleText = "";
        String detailText = "";
        /* 同步车场规则 数据 */
        try {
            parkRuleSync(parkId);
        } catch (BaseException e) {
            _log.error(e.getExceptionMessage(), e);
            exceptionHandle.handle(e);
            simpleText += e.getExceptionMessage().getSimpleText() + ";";
            detailText += e.getExceptionMessage().getDetailText() + ";";
        } catch (Exception e) {
            _log.error(e.getMessage(), e);
            exceptionHandle.handle(e);
            simpleText += "未知" + ";";
            detailText += "未知" + ";";
        }

        /* 同步用户及车辆信息 */
        try {
            userCarInfoSync(parkId);
        } catch (BaseException e) {
            _log.error(e.getExceptionMessage(), e);
            exceptionHandle.handle(e);
            simpleText += e.getExceptionMessage().getSimpleText() + ";";
            detailText += e.getExceptionMessage().getDetailText() + ";";
        } catch (Exception e) {
            _log.error(e.getMessage(), e);
            exceptionHandle.handle(e);
            simpleText += "未知" + ";";
            detailText += "未知" + ";";
        }

        if (!StringUtils.isBlank(simpleText)) {
            throw new ServiceCoreException(ServiceCoreException.TypeEnum.EXCEPTION_NO_DATA_FIND.getId(), null,
                    ExceptionMessage.createExceptionMessage(
                            ServiceCoreException.TypeEnum.EXCEPTION_NO_DATA_FIND.getDesc(), simpleText, detailText));
        }
    }

    /**
     * @Description (TODO同步车场规则)
     * @param parkId
     */
    private void parkRuleSync(int parkId) {

        TbParkspace park = parkCacheInter.queryParkSpace(parkId);

        if (park == null) {
            _log.info("车场列表为空，同步任务已完成");
            throw new ServiceCoreException(ServiceCoreException.TypeEnum.EXCEPTION_NO_DATA_FIND.getId(), null,
                    ExceptionMessage.createExceptionMessage(
                            ServiceCoreException.TypeEnum.EXCEPTION_NO_DATA_FIND.getDesc(), "无此车场", " 车牌=" + parkId));
        }

        // 车场编号
        String parkCode = park.getParkCode();
        // 车场软件供应商编号
        int supplierId = park.getSupplierId();

        List<ApParkTypeInfo> apParkTypeList = bSGBaseDataAdapter.AccountRuleByParkId(parkCode);

        List<TbParkingrule> tbParkRulelist = new ArrayList<TbParkingrule>();

        if (ListUtil.isEmpty(apParkTypeList)) {
            throw new ServiceCoreException(ServiceCoreException.TypeEnum.EXCEPTION_NO_DATA_FIND.getId(), null,
                    ExceptionMessage.createExceptionMessage(
                            ServiceCoreException.TypeEnum.EXCEPTION_NO_DATA_FIND.getDesc(), "此车场没有规则数据",
                            " 车牌=" + parkId));
        }

        for (ApParkTypeInfo aprule : apParkTypeList) {
            // 规则编码 与busyName对应
            String busyID = aprule.getBusyID();
            // 时段类型名称 (0分时段 1高峰时段 2非高峰时段 3非工作日)
            String busyName = aprule.getBusyName();
            // 表示车辆类型 (0摩托车1小型车2大型车3超大型车) 公共部分
            int carTypeCode = aprule.getCarTypeCode();
            // 时段结束时间00:00
            String duringEnd = aprule.getDuringEnd();
            // 时段内费用上限(单位分)
            int duringHighestFee = aprule.getDuringHighestFee();
            // 时段开始时间 00:00
            String duringStart = aprule.getDuringStart();
            // 24小时费用上限(单位分) 公共部分
            int highestFeeOneDay = aprule.getHighestFeeOneDay();
            // 在场时间或首x分钟
            String inParkTime = aprule.getInParkTime();
            // 首x分钟的费用(单位分)
            int inParkTimeCost = aprule.getInParkTimeCost();
            // 项目编码
            String parkIdStr = aprule.getParkId();
            // 规则编码
            int parkTypeID = aprule.getParkTypeID();
            // 规则名称
            String parkTypeName = aprule.getParkTypeName();
            // 单位时间的费用(单位元)
            int perCost = aprule.getPerCost();
            // 单位时间(分钟) 公共部分
            int perTime = aprule.getPerTime();

            TbParkingrule tbParkingrule = new TbParkingrule();
            tbParkingrule.setId(tbParkingruleMapper.nextSeq());
            tbParkingrule.setBusyName(StringUtils.isBlank(busyID) ? -1 : Integer.valueOf(busyID));
            tbParkingrule.setCarTypeCode(carTypeCode);
            tbParkingrule.setCreate_date(new Date());
            tbParkingrule.setDuringEnd(duringEnd);
            tbParkingrule.setDuringHighestFee(duringHighestFee);
            tbParkingrule.setDuringStart(duringStart);
            tbParkingrule.setHighestFeeOneDay(highestFeeOneDay);
            tbParkingrule.setInParkTime(StringUtils.isBlank(inParkTime) ? -1 : Integer.valueOf(inParkTime));
            tbParkingrule.setInParkTimeCost(inParkTimeCost);
            tbParkingrule.setName(parkTypeName);
            tbParkingrule.setParkID(park.getId());
            tbParkingrule.setPerCost(perCost);
            tbParkingrule.setPerTime(perTime);
            tbParkingrule.setStatus(RecordStatusEnum.EFFICIENCY.getStatus());
            tbParkingrule.setUpdate_date(new Date());

            tbParkRulelist.add(tbParkingrule);
        }

        // 保存车场规则列表
        syncParkRuleSave(tbParkRulelist, park);
    }

    @Transactional(rollbackFor = Exception.class)
    private void syncParkRuleSave(List<TbParkingrule> tbParkRulelist, TbParkspace park) {
        int parkid = park.getId();
        int delNum = tbParkingruleMapper.deleteByParkid(parkid);
        _log.info("delete num=" + delNum);
        tbParkingruleMapper.batchInsert(tbParkRulelist);
    }

    /**
     * @Description (TODO根据车场id 同步用户和车辆信息)
     * @param parkId
     */
    private void userCarInfoSync(int parkId) {
        TbParkspace tbParkspace = parkCacheInter.queryParkSpace(parkId);
        if (tbParkspace == null) {
            _log.info("车场列表为空，同步任务已完成");
            throw new ServiceCoreException(ServiceCoreException.TypeEnum.EXCEPTION_NO_DATA_FIND.getId(), null,
                    ExceptionMessage.createExceptionMessage(
                            ServiceCoreException.TypeEnum.EXCEPTION_NO_DATA_FIND.getDesc(), "无此车场", " 车牌=" + parkId));
        }

        _log.info("同步车场的用户数据 size=" + 1);

        String parkCode = tbParkspace.getParkCode();
        int supplierId = tbParkspace.getSupplierId();

        List<ApUserCarInfo> apusercarList = bSGBaseDataAdapter.allUserCar(parkCode);

        syncUser(apusercarList);
        syncUsercaReleation(apusercarList, tbParkspace);
    }

    /**
     * @Description (TODO同步车辆信息并入库)
     * @param apusercarList
     * @param park
     */
    private void syncUsercaReleation(List<ApUserCarInfo> apusercarList, TbParkspace park) {
        int parkId = park.getId();
        int supplierId = park.getSupplierId();
        String parkName = park.getName();
        List<TbCar> tbusercarList = new ArrayList<TbCar>();
        List<TbCar> tbcarhas = tbCarMapper.listByParkid(parkId);
        Set<String> car_carnum_userid = new HashSet<String>();
        Set<String> car_carnum_userid_new = new HashSet<String>();
        for (ApUserCarInfo ap : apusercarList) {
            String tels = ap.getContact_Tel1();
            String[] telArray = tels.split(",");
            for (String t : telArray) {
                if (StringUtils.isBlank(t)) {
                    continue;
                }
                TbUserInfo tbuserinfo = tbUserInfoMapper.queryUserByTel(tel2Long(t));
                if (tbuserinfo == null) {
                    continue;
                }
                int userid = tbuserinfo.getId();
                String carNum = ap.getCarNumber();
                int cardType = ap.getCardType();
                int cardState = ap.getCardState();
                int carType = ap.getCarType();
                int monthFee = ap.getMonthFee();
                String operator = ap.getRequireguy();// 操作员
                String carSpace = ap.getCarpos();// 车位
                Date issueTime = ap.getRequiretime();// 发行时间
                String memeberName = ap.getMember_Name();
                Date expireDate = ap.getExpireDate();
                String cardName = ap.getCardDescript();

                TbCar car = new TbCar();
                car.setParkID(parkId);
                car.setSupplierId(supplierId);
                car.setParkName(parkName);
                car.setUserID(userid);
                car.setCarNum(carNum);
                car.setStatus(cardState);
                car.setCardType(cardType);
                car.setCardExpiration(expireDate);
                car.setCarType(carType);
                car.setMonthFee(monthFee);
                car.setMemberName(memeberName == null ? "" : memeberName);
                car.setCarSpace(carSpace == null ? "" : carSpace);
                car.setIssueTime(issueTime);
                car.setOperator(operator == null ? "" : operator);
                car.setCardName(cardName == null ? "" : cardName);
                tbusercarList.add(car);
            }

        }

        List<TbCar> inserts = new ArrayList<TbCar>();
        List<TbCar> updates = new ArrayList<TbCar>();
        List<TbCar> dels = new ArrayList<TbCar>();

        for (TbCar car : tbcarhas) {
            car_carnum_userid.add(parkId + ":" + car.getCarNum() + ":" + car.getUserID());
        }

        for (TbCar car : tbusercarList) {
            car_carnum_userid_new.add(parkId + ":" + car.getCarNum() + ":" + car.getUserID());
        }

        for (TbCar car : tbusercarList) {
            String tag = park.getId() + ":" + car.getCarNum() + ":" + car.getUserID();
            if (car_carnum_userid.contains(tag)) {
                updates.add(car);
            } else {
                inserts.add(car);
            }
        }

        for (TbCar car : tbcarhas) {
            String tag = park.getId() + ":" + car.getCarNum() + ":" + car.getUserID();
            if (!car_carnum_userid_new.contains(tag)) {
                car.setStatus(CardStatuEnum.DELETED_STATUS.getStatus());
                car.setMemberName(car.getMemberName() == null ? "" : car.getMemberName());
                car.setCarSpace(car.getCarSpace() == null ? "" : car.getCarSpace());
                car.setOperator(car.getOperator() == null ? "" : car.getOperator());
                car.setCardName(car.getCardName() == null ? "" : car.getCardName());
                dels.add(car);
            }
        }

        if (!ListUtil.isEmpty(inserts)) {
            for (TbCar car : inserts) {
                tbCarMapper.insetNoExists(car);
            }

        }
        if (!ListUtil.isEmpty(updates)) {
            tbCarMapper.batchUpdate(updates);
        }
        if (!ListUtil.isEmpty(dels)) {
            tbCarMapper.batchUpdate(dels);
        }

        tbusercarList.clear();
        tbusercarList = null;
        inserts.clear();
        inserts = null;
        updates.clear();
        updates = null;
        dels.clear();
        dels = null;

    }

    /**
     * @Description (TODO同步用户信息并入库)
     * @param apusercarList
     */
    private void syncUser(List<ApUserCarInfo> apusercarList) {
        List<TbUserInfo> tbuserList = new ArrayList<TbUserInfo>();

        Set<String> tagSet = new HashSet<String>();
        if (!ListUtil.isEmpty(apusercarList)) {
            for (ApUserCarInfo ap : apusercarList) {

                String tels = ap.getContact_Tel1();
                String name = ap.getMember_Name();
                String carNum = ap.getCarNumber();
                String homeAddr = ap.getHome_Address();
                String[] telArray = tels.split(",");
                for (String t : telArray) {
                    if (StringUtils.isBlank(t) || tagSet.contains(t)) {
                        continue;
                    }
                    TbUserInfo u = new TbUserInfo();
                    u.setTel(tel2Long(t));
                    tbuserList.add(u);
                    u.setName(name);
                    u.setHomeAddr(homeAddr);

                    tagSet.add(t);
                }
            }

            for (TbUserInfo userInfo : tbuserList) {
                userInfo.setUserType(UserTypeEnum.REGISTER_USER.getType());
                int num = tbUserInfoMapper.update(userInfo);

                userInfo.setUserType(UserTypeEnum.REGISTER_USER.getType());
                userDBAtomic.register_loginUser(userInfo);

            }
        }

    }

    private long tel2Long(String str) {

        long tel = -1L;

        try {
            tel = Long.valueOf(str);
        } catch (Exception e) {
            _log.error(e, e);
        }
        return tel;
    }

}
